package com.abl.service.system.impl;

import com.abl.common.security.ApiHandler;
import com.abl.common.cache.CacheKey;
import com.abl.common.cache.CacheService;
import com.abl.common.mybatis.dao.Dao;
import com.abl.common.mybatis.model.Dnt;
import com.abl.common.mybatis.strengthen.Wrapper;
import com.abl.common.util.IdKit;
import com.abl.common.util.StringKit;
import com.abl.common.util.coll.ArrayKit;
import com.abl.service.system.SysService;
import com.alibaba.fastjson2.JSON;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;
import java.util.stream.Collectors;

/**
 * 字典表实现
 */
@Slf4j
@Service
public class SysServiceImpl implements SysService {

    @Autowired
    private Dao dao;

    @Autowired
    private CacheService cache;

    //项目初始化
    @Override
    public void init() {
        //扫描API信息并插入数据库
        scanApiToDb();
        //刷新系统级别缓存
        //角色资源
        //角色菜单
    }


    /**
     * 从缓存中获取字典数据
     */
    @Override
    public List<Dnt> allDict() {
        String KEY = CacheKey.DICT_ALL.key();
        String value = cache.get(KEY);

        if (value == null) {
            Wrapper<Object> wrapper = new Wrapper<>();
            wrapper.eq("d_s", "0");
            List<Dnt> sys_dict = dao.list("sys_dict", wrapper);
            //插入缓存
            cache.set(KEY, JSON.toJSONString(sys_dict));
            return sys_dict;
        }

        return JSON.parseArray(value, Dnt.class);
    }

    /**
     * 从缓存中获取字典数据
     */
    @Override
    public Dnt dict(String code) {
        Optional<Dnt> first = allDict().stream().filter(dict -> dict.getString("code").equals(code)).findFirst();
        return first.get();
    }

    @Override
    public String dictValue(String code) {
        return dictValue(code, null);
    }

    @Override
    public String dictValue(String code, String defaultValue) {
        Dnt dict = dict(code);
        if (dict != null) {
            return dict.getString("value");
        }
        return defaultValue;
    }

    @Override
    public List<Dnt> allApi() {
        String KEY = CacheKey.API_ALL.key();
        String value = cache.get(KEY);

        if (value == null) {
            Wrapper<Object> wrapper = new Wrapper<>();
            wrapper.eq("d_s", "0");
            List<Dnt> sys_dict = dao.list("sys_api", wrapper);
            //插入缓存
            cache.set(KEY, JSON.toJSONString(sys_dict));
            return sys_dict;
        }

        return JSON.parseArray(value, Dnt.class);
    }

    //角色对应的API
    @Override
    public List<String> roleApiPath(Object roleId) {
        //存在缓存直接返回
        String KEY = CacheKey.LINK_ROLE_API.key() + roleId;
        String value = cache.get(KEY);
        if (value != null) return JSON.parseArray(value, String.class);

        //查询角色对应API,放入缓存后返回
        Wrapper<Object> qW = new Wrapper<>();
        qW.select("api_id");
        qW.eq("role_id", roleId);
        List<String> apiIds = dao.listObj("sys_link_role_api", qW, String.class);

        if (ArrayKit.isNotBlank(apiIds)) {
            Set<String> paths = allApi().stream()
                    //过滤id相等的数据
                    .filter(api -> apiIds.contains(api.getString("id")))
                    //取path属性
                    .map(e -> e.getString("path"))
                    //转为set数组
                    .collect(Collectors.toSet());

            cache.set(KEY, JSON.toJSONString(paths));
            //返回查询到的关联API路径数组
            return new ArrayList<>(paths);
        }

        //什么都没有，返回空
        return new ArrayList<>();
    }

    @Override
    public List<String> roleApiPath(List<Object> roleIds) {
        HashSet<String> set = new HashSet<>();

        for (Object roleId : roleIds) {
            List<String> apiPathList = roleApiPath(roleId);
            set.addAll(apiPathList);
        }

        return new ArrayList<>(set);
    }

    //扫描API信息并插入数据库
    @Transactional(rollbackFor = Exception.class)
    @Override
    public void scanApiToDb() {
        HashMap<String, ArrayList<HashMap<String, Object>>> scanRes = ApiHandler.scanApi();
        ArrayList<HashMap<String, Object>> mList = scanRes.get("mList");
        Set<Object> pathSet = new HashSet<>();
        Set<Object> mpath = mList.stream().map(e -> e.get("path")).collect(Collectors.toSet());
        pathSet.addAll(mpath);

        //查询已存在资源
        Wrapper<Object> wrapper = new Wrapper<>();
        wrapper.select("id,path");
        wrapper.in("path", pathSet);
        wrapper.eq("d_s", 0);
        List<Dnt> nowHasList = dao.list("sys_api", wrapper);

        //更新已存在的资源
        mList.forEach(m -> {
            nowHasList.forEach(dnt -> {
                String pathM = m.get("path").toString();
                if (pathM.equals(dnt.getString("path"))) {
                    //TODO 更新已存在的资源
                    //request_type	varchar	10		False	False		请求方式（POST/GET）
                    //method_name	varchar	64		False	False		方法名（不可修改，服务启动自动更新）
                    //class_name	varchar	32		False	False		类名（不可修改，服务启动自动更新）
                    //package	varchar	500		False	False		包名（不可修改，服务启动自动更新）
                    //class_path	varchar	500		False	False		类路径（不可修改，服务启动自动更新）

                }
            });
        });
        dao.updateBatchById("sys_api", nowHasList);

        //插入不存在的资源
        List<String> inDbRes = nowHasList.stream().map(e -> e.getString("path")).toList();
        List<HashMap<String, Object>> addMList = mList.stream().filter(e -> !inDbRes.contains(e.get("path").toString())).collect(Collectors.toList());

        ArrayList<Dnt> addM = new ArrayList<>();
        //{parentName=模板表, name=模板表, path=/aTemplate/aTemplate}
        //{parentName=模板表, parentPath=/aTemplate/aTemplate, name=新增, path=/aTemplate/aTemplate/add},
        //TODO 可以优化
        for (HashMap<String, Object> m : addMList) {
            String mPath = m.get("path").toString();
            Dnt em = Dnt.createInsert();
            em.put("id", IdKit.getId());

            //模块名称（默认取Controller名）
            em.put("module_name", m.get("parentName"));
            if (StringKit.isNotBlank(m.get("module").toString())) {
                em.put("module_name", m.get("module"));
            }

            em.put("api_name", m.get("name"));
            em.put("path", mPath);
            em.put("check_login", m.get("login"));
            em.put("check_permission", m.get("permission"));
            em.put("check_re_submit", m.get("reSubmit"));
            em.put("log_open_action", m.get("actionLog"));
            em.put("log_save_request", m.get("saveLogRequest"));
            em.put("log_save_response", m.get("saveLogResponse"));
            em.put("sort", 100);

            em.put("method_name", m.get("method_name"));
            em.put("class_name", m.get("class_name"));
            em.put("package", m.get("package"));


            //TODO
            //            method_name	varchar	64		False	False		方法名（不可修改，服务启动自动更新）
            //            class_name	varchar	32		False	False		类名（不可修改，服务启动自动更新）
            //            package	varchar	500		False	False		包名（不可修改，服务启动自动更新）
            //            class_path	varchar	500		False	False		类路径（不可修改，服务启动自动更新）


            addM.add(em);
        }
        dao.insertBatch("sys_api", addM);
        log.info("【addM】" + JSON.toJSONString(addM));
    }

//    public void scanApiToDb() {
//        HashMap<String, ArrayList<HashMap<String, Object>>> scanRes = ApiAnnotationHandler.scanApi();
//        ArrayList<HashMap<String, Object>> cList = scanRes.get("cList");
//        ArrayList<HashMap<String, Object>> mList = scanRes.get("mList");
//        Set<Object> pathSet = new HashSet<>();
//        Set<Object> cpath = cList.stream().map(e -> e.get("path")).collect(Collectors.toSet());
//        Set<Object> mpath = mList.stream().map(e -> e.get("path")).collect(Collectors.toSet());
//        pathSet.addAll(cpath);
//        pathSet.addAll(mpath);
//
//        //查询已存在资源
//        Wrapper<Object> wrapper = new Wrapper<>();
//        wrapper.select("id,pid,path");
//        wrapper.in("path", pathSet);
//        wrapper.eq("d_s", 0);
//        List<Dnt> nowHasList = dao.list("sys_api", wrapper);
//
//        //更新已存在的资源
//        cList.forEach(c -> {
//            nowHasList.forEach(dnt -> {
//                String path = c.get("path").toString();
//                if (path.equals(dnt.getString("path"))) {
//                    dnt.set("controller_name", c.get("name"));
//                    dnt.set("api_name", c.get("name"));
//                }
//            });
//        });
//
//        mList.forEach(m -> {
//            nowHasList.forEach(dnt -> {
//                String pathM = m.get("path").toString();
//                if (pathM.equals(dnt.getString("path"))) {
//                    dnt.set("api_name", m.get("name"));
//                    dnt.set("controller_name", m.get("parentName"));
//                }
//            });
//        });
//        dao.updateBatchById("sys_api", nowHasList);
//
//
//        //插入不存在的资源
//        List<String> inDbRes = nowHasList.stream().map(e -> e.getString("path")).toList();
//        List<HashMap<String, Object>> addCList = cList.stream().filter(e -> !inDbRes.contains(e.get("path").toString())).collect(Collectors.toList());
//        List<HashMap<String, Object>> addMList = mList.stream().filter(e -> !inDbRes.contains(e.get("path").toString())).collect(Collectors.toList());
//
//        ArrayList<Dnt> addC = new ArrayList<>();
//        ArrayList<Dnt> addM = new ArrayList<>();
//        //{parentName=模板表, name=模板表, path=/aTemplate/aTemplate}
//        for (HashMap<String, Object> c : addCList) {
//            Object cPath = c.get("path").toString();
//            Dnt ec = Dnt.createInsert();
//            ec.put("id", IdKit.getId());
//            ec.put("pid", "0");
//            ec.put("controller_name", c.get("name"));
//            ec.put("module_name", c.get("name"));
//            ec.put("level", "1");
//            ec.put("api_name", c.get("name"));
//            ec.put("api_name", c.get("name"));
//            ec.put("path", cPath);
//            ec.put("ids", "[\"" + ec.getString("id") + "\"]");
//            addC.add(ec);
//        }
//        log.info("【addC】" + JSON.toJSONString(addC));
//        dao.insertBatch("sys_api", addC);
//
//        //{parentName=模板表, parentPath=/aTemplate/aTemplate, name=新增, path=/aTemplate/aTemplate/add},
//        //TODO 可以优化
//        for (HashMap<String, Object> m : addMList) {
//            String parentPath = m.get("parentPath").toString();
//            Wrapper<Object> qw = new Wrapper<>();
//            qw.select("id,level,api_name");
//            qw.eq("d_s", 0);
//            qw.eq("path", parentPath);
//
//            Dnt parentName = dao.selectOne("sys_api", qw);
//
//            String mPath = m.get("path").toString();
//            Dnt em = Dnt.createInsert();
//            em.put("id", IdKit.getId());
//            em.put("pid", parentName.getString("id"));
//            em.put("controller_name", parentName.getString("api_name"));
//            em.put("module_name", parentName.get("api_name"));
//
//            em.put("level", parentName.getIntValue("level") + 1);
//            em.put("api_name", m.get("name"));
//            em.put("api_name", m.get("name"));
//            em.put("path", mPath);
//
//            em.put("check_login", m.get("login"));
//            em.put("check_permission", m.get("permission"));
//            em.put("check_re_submit", m.get("reSubmit"));
//
//            String pids = "[" + "\"" + parentName.getString("id") + "\"" + ",\"" + em.getString("id") + "\"" + "]";
//            em.put("ids", pids);
//            addM.add(em);
//        }
//
//        dao.insertBatch("sys_api", addM);
//        log.info("【addM】" + JSON.toJSONString(addM));
//    }

    @Override
    public Dnt api(String path) {
        if (path != null) {
            Optional<Dnt> api = allApi().stream().filter(e -> path.equals(e.getString("path"))).findFirst();
            return api.get();
        }
        return null;
    }

    //添加缓存KEY，用作管理端查询
//    public void addCacheKey(String KEY) {
//        String s = cache.get(CacheKey.ALL_KEY.key());
//        List<String> keys = JSON.parseArray(s);
//        HashSet<String> keySet = new HashSet<>(keys);
//        keySet.add(KEY);
//        cache.set(CacheKey.ALL_KEY.key(), JSON.toJSONString(keySet));
//    }

    //添加缓存KEY，用作管理端查询
//    public List<String> allCacheKey() {
//        return JSON.parseArray(cache.get(CacheKey.ALL_KEY.key()));
//    }
}
